package com.common.Util;

import com.common.annotation.FieldMap;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @program: BigPanel
 * @description: 对象工具集合
 * @author: 无恙
 * @create: 2024-05-07 12:35
 **/


public class ObjectUtil {
    //判断对象是否为空
    public static <T> boolean  isEmpty(T obj){

        if(obj instanceof String){
            return ((String)obj).isEmpty();
        }

        Optional<T> optional = Optional.ofNullable(obj);
        return !optional.isPresent();
    }

    //判断对象是否相同
    public static <T> boolean equals(T obj1,T obj2){
        Optional<T> optional1 = Optional.ofNullable(obj1);
        Optional<T> optional2 = Optional.ofNullable(obj2);
        return optional1.equals(optional2);
    }
    //DO转VO
    public static <D, V> V covert(D sourceClass, Class<V> targetClass ) throws InstantiationException, IllegalAccessException {
        V target = targetClass.newInstance();
        //获取目标类字段
        Field[] targetFields = targetClass.getDeclaredFields();
        //获取资源类字段
        Field[] sourceFields = sourceClass.getClass().getDeclaredFields();

        //获取资源类字段和目标类字段
        HashMap<String, Field> targetFieldMap = new HashMap<>();
        for (Field targetField : targetFields) {
            targetField.setAccessible(true);
            targetFieldMap.put(targetField.getName(), targetField);
        }

        for (Field sourceField : sourceFields) {
            sourceField.setAccessible(true);
            Field targetField = targetFieldMap.get(sourceField.getName());
            if (targetField != null && sourceField.getType().equals(targetField.getType())) {
                targetField.set(target, sourceField.get(sourceClass));
            }
        }

        return target;
    }


    public static  <T> T CopyProperties(Class<T> target, Object... sources) throws IllegalAccessException {
        // 如果目标对象为空，或者源对象数组为空，直接返回空
        if (isEmpty(target) || sources == null || sources.length == 0) {
            return null;
        }

        // 创建目标对象实例
        T tar ;
        try {
            tar = target.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException("Failed to create an instance of target class", e);
        }
        // 用于存储目标对象的字段名与字段对象的映射关系
        Map<String, Field> targetFieldMap = new HashMap<>();
        // 获取目标对象的所有字段
        Field[] targetFields = target.getDeclaredFields();

        // 将目标对象的字段名与字段对象进行映射存储
        for (Field targetField : targetFields) {
            targetField.setAccessible(true);
            targetFieldMap.put(targetField.getName(), targetField);
        }

        // 遍历源对象数组
        for (Object object : sources) {
            // 获取源对象的所有字段
            Field[] sourceFields = object.getClass().getDeclaredFields();

            // 遍历源对象的字段
            for (Field field : sourceFields) {
                field.setAccessible(true);
                // 判断字段上是否存在FieldMap注解
                if (field.isAnnotationPresent(FieldMap.class)) {
                    // 获取FieldMap注解
                    FieldMap[] annotation = field.getAnnotationsByType(FieldMap.class);
                    FieldMap fieldMap = Arrays.stream(annotation)
                            .filter(a -> a.targetType().equals(target))
                            .findFirst()
                            .orElse(null);
                    //相应注解目标对象是tar
                    if (!isEmpty(fieldMap)){
                        assert fieldMap != null;
                        // 根据FieldMap注解指定的属性名映射值到目标对象的对应字段

                        Field targetField = targetFieldMap.get(fieldMap.propertyName());
                        //判断tar的targetField是否已经赋值
                        if(targetField.get(tar)!=null){
                            continue;
                        }
                        targetField.set(tar, field.get(object));
                        continue;

                    }
                }

                // 若字段上未标注FieldMap注解，则根据字段名直接映射值到目标对象的对应字段
                Field targetField = targetFieldMap.get(field.getName());
                if (targetField != null) {
                    if(targetField.get(tar)!=null){
                        continue;
                    }
                    targetField.set(tar, field.get(object));
                }

            }
        }

        // 返回填充后的目标对象
        return tar;
    }


}
